import fs from 'fs'
import fg from 'fast-glob'
/*
  不在layout子路由下的路由名单
*/
const notLayoutChidRouts = ['login']
/**
 * 根据comPath或者name返回() => import(path)
 */
function handleCom(item: RouteItem, keyPath: string) {
  keyPath = keyPath.replace('/src', '@')
  keyPath = keyPath.replace('/route.ts', '')
  let path = ''
  if (item.comPath) {
    if (item.comPath.startsWith('./')) {
      path = keyPath + item.comPath.slice(1) // 去掉.
    } else if (item.comPath.startsWith('../')) {
      const len1 = Number(item.comPath.match(/\.\.\//g)?.length)
      const len2 = keyPath.split('/').slice(1, -len1)
      if (len2.length) {
        len2.unshift('@')
        path = len2.join('/') + '/' + item.comPath.replaceAll('../', '')
      }
      throw new Error(`${item.title} 路由中的comPath格式不正确`)
    } else if (item.comPath.startsWith('@/views/')) {
      path = item.comPath
    } else {
      throw new Error(`${item.title} 路由中的comPath格式不规范`)
    }
  } else {
    path = `${keyPath}/${item.name}/index.vue`
  }
  return `() => import('${path}')`
}
/**
 * 寻找判断子路由，给children添加数据
 */
function lookChildRoute(item: RouteItem, context: ObjIndex, keyPath: string, parentPath: string, isLayoutChid: boolean) {
  if (item.comPath) {
    if (item.comPath.startsWith('./')) {
      keyPath = keyPath.replace('/route.ts', '') + item.comPath.slice(1)
    } else if (item.comPath.startsWith('../')) {
      return ''
    } else if (item.comPath.startsWith('@/views/')) {
      keyPath = item.comPath.replace('@', '/src')
    }
  } else {
    const pathArr = keyPath.split('/')
    pathArr.splice(-1, 0, item.name)
    keyPath = pathArr.join('/')
  }
  if (context[keyPath]) return computedRoute(keyPath, context, parentPath, isLayoutChid)
  return ''
}

function computedRoute(keyPath: string, context: ObjIndex, parentPath: string, isLayoutChid: boolean): string {
  let arr: RouteItem[] = []
  if (keyPath === '/src/views/route.ts') {
    if (isLayoutChid) {
      arr = context['/src/views/route.ts'].default.filter((item: RouteItem) => !notLayoutChidRouts.includes(item.name))
    } else {
      arr = context['/src/views/route.ts'].default.filter((item: RouteItem) => notLayoutChidRouts.includes(item.name))
    }
  } else {
    arr = context[keyPath].default
  }
  return arr.reduce((total: string, item: RouteItem) => {
    if (parentPath === '/') parentPath = ''
    const path = item.path ? item.path : parentPath + '/' + item.name
    const obj = `{
      path: '${path}',
      name: '${item.name}',
      ${item.redirect ? "redirect: '" + item.redirect + "'," : ''}
      meta: {
        title: '${item.title}',
        hidden: ${item.hidden === undefined ? false : item.hidden},
        icon: ${item.icon === undefined ? "''" : item.icon},
        rank: ${item.rank === undefined ? 0 : item.rank},
        subMenu: ${item.subMenu === undefined ? false : item.subMenu},
        keepAlive: ${item.keepAlive === undefined ? false : item.keepAlive},
        id: ${item.id},
      },
      ${!item.subMenu ? 'component: ' + handleCom(item, keyPath) + ',' : ''}
      children: [
        ${lookChildRoute(item, context, keyPath, path, isLayoutChid)}
      ],
    },`
    total += obj
    return total
  }, '')
}
/**
 * 根据views目录下的route.ts生成路由表
 */

async function genRouters() {
  /*
    两种错误情况：
      1、忘记在上级route.ts配置,解决，不会遍历没配置的子路由
      2、
      3、有配置但是没有文件
    需要考虑name重复问题，重复直接抛错

    几个有作用的key，name,comPath

    得到import(path)
    import(path)中的path要全部变成'../views/....../index.vue'格式
    先判断comPath：{
      ./开头直接连接
      ../开头splice再连接
      @/views/开头，把@/views/替换成../views/，如果不是以@/views/开头，则抛错
    }
    没有comPath，判断name: 直接连接name

    判断子路由
    先判断comPath：{
      ./开头直接连接，通过context[key]得到子路由
      ../开头，不符合规则，直接判定没有子路由
      @/views/开头，把@/views/替换成../views后，比较和./开头的格式，不相等则直接判定没有子路由，不符合规则
    }
    判断name: 直接连接name，通过context[key]得到子路由
  */
  const context: ObjIndex = {}
  const files = await fg('src/views/**/route.ts')
  // 弄成import.meta.glob的输出格式，genRouters.ts是之前的写法，但是编译打包后路由会出现问题
  for (let i = 0; i < files.length; i++) {
    const module = await import(files[i].replace('src/', '../'))
    files[i] = '/' + files[i]
    context[files[i]] = module
  }
  // 从顶级路由开始计算
  const routes = `
  import type { RouteRecordRaw } from 'vue-router'
  const routes: RouteRecordRaw[] = [
    {
      path: '/',
      name: 'layout',
      redirect: '/home',
      component: () => import('@/layout/index.vue'),
      meta:{
        title: 'layout',
      },
      children: [
        ${computedRoute('/src/views/route.ts', context, '', true)}
      ]
    },
    ${computedRoute('/src/views/route.ts', context, '', false)}
  ]
  export default routes`

  return routes
}
genRouters().then((context) => {
  const routesFile = './src/router/asyncRoutesMap.ts'
  fs.writeFileSync(routesFile, context)
})
